/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "spatial_rdb_manager.h"

#include "dummy_values_bucket.h"
#include "spatial_awareness_common.h"
#include "msdp_algorithm_common.h"
#include "constants.h"

using namespace OHOS::NativeRdb;
using namespace OHOS::Utils;
namespace OHOS {
namespace Msdp {
SpatialRdbManager::SpatialRdbManager() : timer_("RdbTimer") {}

bool SpatialRdbManager::Init(int mode)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s Init", __func__);
    int32_t ret = CreateRdbStore();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "Init: failed to create rdb store");
        return ret;
    }

    SpatialTimer::NotifyTask task;
    switch (mode) {
        case CMD_DIRECTION: {
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateDirectionData, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        case CMD_DISTANCE: {
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateDistanceData, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        case CMD_ANGLE: {
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateAngleData, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        case CMD_INNEROUTER: {
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateInnerOuterData, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        case CMD_EXIST: {
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateExistData, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        case CMD_COMMON: {
            InsertSpatialRelation(store_);
            timerUtils_ = std::make_shared<SpatialTimer>();
            task = std::bind(&SpatialRdbManager::UpdateSpatialRelation, this);
            timerUtils_->Start(TIMER_INTERVAL, task);
            break;
        }
        default:
            break;
    }
    return true;
}

void SpatialRdbManager::RegisterEventCallback(int mode, SpatialEventCallback& callback)
{
    switch (mode) {
        case CMD_DIRECTION: {
            directionCb_ = callback;
            break;
        }
        case CMD_DISTANCE: {
            distanceCb_ = callback;
            break;
        }
        case CMD_ANGLE: {
            angleCb_ = callback;
            break;
        }
        case CMD_INNEROUTER: {
            innerOuterCb_ = callback;
            break;
        }
        case CMD_EXIST: {
            existCb_ = callback;
            break;
        }
        case CMD_COMMON: {
            commonCb_ = callback;
            break;
        }
        default:
            break;
    }
}

void SpatialRdbManager::UpdateSpatialEventData(int mode)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateSpatialEventData: enter");
    switch (mode) {
        case CMD_DIRECTION: {
            CheckSpatialDirectionValue(store_);
            CheckDeviceData(mode, store_);
            directionCb_(directionEvent_);
            break;
        }
        case CMD_DISTANCE: {
            CheckSpatialDistanceValue(store_);
            CheckDeviceData(mode, store_);
            distanceCb_(distanceEvent_);
            break;
        }
        case CMD_ANGLE: {
            CheckSpatialAngleValue(store_);
            CheckDeviceData(mode, store_);
            angleCb_(angleEvent_);
            break;
        }
        case CMD_INNEROUTER: {
            CheckSpatialInnerOuterValue(store_);
            CheckDeviceData(mode, store_);
            innerOuterCb_(innerOuterEvent_);
            break;
        }
        case CMD_EXIST: {
            CheckSpatialExistValue(store_);
            CheckDeviceData(mode, store_);
            existCb_(existEvent_);
            break;
        }
        case CMD_COMMON: {
            CheckSpatialRelation(store_);
            commonCb_(commonEvent_);
            break;
        }
        default: {
            break;
        }
    }
}

int32_t SpatialRdbManager::CreateRdbStore()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "CreateRdbStore: enter");
    int errCode = SPATIALMANAGER_OK;
    RdbStoreConfig config(DATABASE_NAME);
    InsertOpenCallback helper;
    store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode);
    return SPATIALMANAGER_OK;
}

void SpatialRdbManager::InsertSpatialRelation(std::shared_ptr<RdbStore> &store)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "InsertSpatialRelation: enter");
    int64_t id;
    int ret = store->ExecuteSql(SQL_CREATE_TABLE_SPATIAL_RELATION);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "failed to execute");
        return;
    }
    commonValues_.PutInt("ID", 1);
    commonValues_.PutInt("DIRECTION", -1);
    commonValues_.PutDouble("DISTANCE", -1.0);
    commonValues_.PutDouble("ANGLE", -1.0);
    commonValues_.PutInt("INNER_OUTER", -1);
    commonValues_.PutInt("EXIST", -1);
    ret = store->Insert(id, "SPATIAL_RELATION", commonValues_);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "failed to insert table");
        return;
    }
}

void SpatialRdbManager::UpdateSpatialRelation()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateSpatialRelation: enter");
    int changedRows;
    static std::default_random_engine eng;
    static std::uniform_int_distribution<int> dirDistr(DIRECTION_MIN_VALUE, DIRECTION_MAX_VALUE);
    static std::uniform_real_distribution<double> disDistr(DISTANCE_MIN_VALUE, DISTANCE_MAX_VALUE);
    static std::uniform_real_distribution<double> angDistr(ANGLE_MIN_VALUE, ANGLE_MAX_VALUE);

    (void)eng.seed(time(0));
    int direction = dirDistr(eng);
    double distance = disDistr(eng);
    double angle = angDistr(eng);
    SPATIAL_LOGE(MODULE_ALGORITHM, "direction:%{public}d, distance:%{public}lf, angle:%{public}lf",
        direction, distance, angle);
    commonValues_.Clear();
    commonValues_.PutInt("ID", 1);
    commonValues_.PutInt("DIRECTION", direction);
    commonValues_.PutDouble("DISTANCE", distance);
    commonValues_.PutDouble("ANGLE", angle);
    std::vector<std::string> idList = {"1"};
    int32_t ret = store_->Update(changedRows, "SPATIAL_RELATION",
        commonValues_, "id = ?", idList);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "UpdateDirectionData: failed to update data");
        return;
    }
    UpdateSpatialEventData(CMD_COMMON);
}

void SpatialRdbManager::CheckSpatialRelation(std::shared_ptr<NativeRdb::RdbStore> &store)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "CheckSpatialRelation: enter");

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }
    std::unique_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM SPATIAL_RELATION");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }
    int32_t ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    }
    GetSpatialData(resultSet);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to close", __func__);
        return;
    };
}

void SpatialRdbManager::GetSpatialData(std::unique_ptr<NativeRdb::ResultSet> &resultSet)
{
    int columnIndex;
    int directionValue;
    double distanceValue;
    double angleValue;
    int id;
    int32_t ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
        return;
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
        return;
    }
    ret = resultSet->GetColumnIndex("DIRECTION", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: directionValue is nullptr", __func__);
        return;
    }
    ret = resultSet->GetInt(columnIndex, directionValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: directionValue value is nullptr", __func__);
        return;
    }
    ret = resultSet->GetColumnIndex("DISTANCE", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: distance is nullptr", __func__);
        return;
    }
    ret = resultSet->GetDouble(columnIndex, distanceValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: distanceValue value is nullptr", __func__);
        return;
    }
    ret = resultSet->GetColumnIndex("ANGLE", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: angle is nullptr", __func__);
        return;
    }
    ret = resultSet->GetDouble(columnIndex, angleValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: angle value is nullptr", __func__);
        return;
    }
    commonEvent_.angle = angleValue;
    commonEvent_.distance = distanceValue;
    commonEvent_.direction = static_cast<SpatialDirection>(directionValue);
}

void SpatialRdbManager::CheckSpatialDirectionValue(std::shared_ptr<RdbStore> &store)
{
    SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: enter", __func__);
    int columnIndex;
    int directionValue;
    int32_t ret = -1;
    int id;

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_RELATION WHERE ID = (SELECT max(ID) from SPATIAL_RELATION)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to first row", __func__);
    ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to lastRow", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }
    ret = resultSet->GetColumnIndex("DIRECTION", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: directionValue is nullptr", __func__);
    }

    ret = resultSet->GetInt(columnIndex, directionValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: directionValue value is nullptr", __func__);
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: directionValue = %{public}d",
        __func__, directionValue);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
    if (directionValue >= DIRECTION_SCOPE_MIN && directionValue <= DIRECTION_MAX_VALUE) {
        directionEvent_.direction = static_cast<SpatialDirection>(directionValue);
        directionEvent_.mode = directionEvent_.mode | DIRECTION_MODE;
    }
}

void SpatialRdbManager::CheckSpatialDistanceValue(std::shared_ptr<RdbStore> &store)
{
    int columnIndex;
    double distanceValue;
    int ret = -1;
    int id;

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_RELATION WHERE ID = (SELECT max(ID) from SPATIAL_RELATION)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }

    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to first row", __func__);
    ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to first", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }
    ret = resultSet->GetColumnIndex("DISTANCE", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: distanceValue is nullptr", __func__);
    }
    ret = resultSet->GetDouble(columnIndex, distanceValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: distanceValue value is nullptr", __func__);
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: distanceValue = %{public}f",
        __func__, distanceValue);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
    if (distanceValue >= DISTANCE_SCOPE_MIN) {
        distanceEvent_.distance = distanceValue;
        distanceEvent_.mode = distanceEvent_.mode | DISTANCE_MODE;
    }
}

void SpatialRdbManager::CheckSpatialAngleValue(std::shared_ptr<RdbStore> &store)
{
    int32_t ret = -1;
    int columnIndex;
    double angleValue;
    int id;

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_RELATION WHERE ID = (SELECT max(ID) from SPATIAL_RELATION)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to last row", __func__);
    ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to lastRow", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }

    ret = resultSet->GetColumnIndex("ANGLE", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: angleValue is nullptr", __func__);
    }
    ret = resultSet->GetDouble(columnIndex, angleValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: angleValue value is nullptr", __func__);
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: angleValue = %{public}f",
        __func__, angleValue);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
    if (angleValue >= ANGLE_SCOPE_MIN && angleValue <= ANGLE_SCOPE_MAX) {
        angleEvent_.angle = angleValue;
        angleEvent_.mode = angleEvent_.mode | ANGLE_MODE;
    }
}

void SpatialRdbManager::CheckSpatialInnerOuterValue(std::shared_ptr<RdbStore> &store)
{
    int32_t ret = -1;
    int columnIndex;
    int ioValue;
    int id;

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_RELATION WHERE ID = (SELECT max(ID) from SPATIAL_RELATION)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to last row", __func__);
    ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to lastRow", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }

    ret = resultSet->GetColumnIndex("INNER_OUTER", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: ioValue is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, ioValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: ioValue value is nullptr", __func__);
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: ioValue = %{public}d",
        __func__, ioValue);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
    if (ioValue >= IO_SCOPE_MIN && ioValue <= IO_MAX_VALUE) {
        innerOuterEvent_.innerOuter = static_cast<bool>(ioValue);
        innerOuterEvent_.mode = innerOuterEvent_.mode | INNEROUTER_MODE;
    }
}

void SpatialRdbManager::CheckSpatialExistValue(std::shared_ptr<RdbStore> &store)
{
    int columnIndex;
    int existValue;
    int32_t ret = -1;
    int id;

    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_RELATION WHERE ID = (SELECT max(ID) from SPATIAL_RELATION)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }

    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to last row", __func__);
    ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to lastRow", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }
    ret = resultSet->GetColumnIndex("EXIST", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: existValue is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, existValue);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: existValue value is nullptr", __func__);
    }
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: existValue = %{public}d",
        __func__, existValue);
    ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
    if (existValue >= EXIST_SCOPE_MIN && existValue <= EXIST_MAX_VALUE) {
        existEvent_.exist = static_cast<bool>(existValue);
        existEvent_.mode = existEvent_.mode | EXIST_MODE;
    }
}

void SpatialRdbManager::UpdateDirectionData()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateDirectionData: enter");
    UpdateSpatialEventData(CMD_DIRECTION);
}

void SpatialRdbManager::UpdateDistanceData()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateDistanceData: enter");
    UpdateSpatialEventData(CMD_DISTANCE);
}

void SpatialRdbManager::UpdateAngleData()
{
    UpdateSpatialEventData(CMD_ANGLE);
}

void SpatialRdbManager::UpdateInnerOuterData()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateInnerOuterData: enter");
    UpdateSpatialEventData(CMD_INNEROUTER);
}

void SpatialRdbManager::UpdateExistData()
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "UpdateExistData: enter");
    UpdateSpatialEventData(CMD_EXIST);
}

void SpatialRdbManager::CheckDeviceData(int mode, std::shared_ptr<RdbStore> &store)
{
    if (store == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: store is nullptr", __func__);
        return;
    }

    std::unique_ptr<ResultSet> resultSet =
        store->QuerySql("SELECT * FROM SPATIAL_DEVICE WHERE ID = (SELECT max(ID) from SPATIAL_DEVICE)");
    if (resultSet == nullptr) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: resultSet is nullptr", __func__);
        return;
    }
    GetDeviceData(mode, resultSet);
    int32_t ret = resultSet->Close();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: first row is nullptr", __func__);
        return;
    };
}

void SpatialRdbManager::GetDeviceData(int32_t mode, std::unique_ptr<NativeRdb::ResultSet> &resultSet)
{
    int columnIndex;
    std::string deviceId;
    std::string deviceName;
    int deviceType;
    int id;
    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: Go to last row", __func__);
    int ret = resultSet->GoToFirstRow();
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: failed to go to lastRow", __func__);
        return;
    }

    ret = resultSet->GetColumnIndex("ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, id);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: id value is nullptr", __func__);
    }
    ret = resultSet->GetColumnIndex("DEVICE_ID", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: columnIndex is nullptr", __func__);
    }
    ret = resultSet->GetString(columnIndex, deviceId);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: deviceId value is nullptr", __func__);
    }

    ret = resultSet->GetColumnIndex("DEVICE_NAME", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: columnIndex is nullptr", __func__);
    }
    ret = resultSet->GetString(columnIndex, deviceName);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: deviceName value is nullptr", __func__);
    }

    ret = resultSet->GetColumnIndex("DEVICE_TYPE", columnIndex);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: columnIndex is nullptr", __func__);
    }
    ret = resultSet->GetInt(columnIndex, deviceType);
    if (ret != SPATIALMANAGER_OK) {
        SPATIAL_LOGE(MODULE_ALGORITHM, "%{public}s: deviceType value is nullptr", __func__);
    }

    SPATIAL_LOGI(MODULE_ALGORITHM, "%{public}s: deviceId:%{public}s, deviceName:%{public}s, deviceType:%{public}d",
        __func__, deviceId.c_str(), deviceName.c_str(), deviceType);
    UpdateDeviceData(mode, deviceType, deviceId, deviceName);
}

void SpatialRdbManager::UpdateDeviceData(int mode, int deviceType,
    const std::string deviceId, const std::string deviceName)
{
    switch (mode) {
        case CMD_DIRECTION: {
            directionEvent_.device.deviceId = deviceId;
            directionEvent_.device.deviceName = deviceName;
            directionEvent_.device.typeId = deviceType;
            break;
        }
        case CMD_DISTANCE: {
            distanceEvent_.device.deviceId = deviceId;
            distanceEvent_.device.deviceName = deviceName;
            distanceEvent_.device.typeId = deviceType;
            break;
        }
        case CMD_ANGLE: {
            angleEvent_.device.deviceId = deviceId;
            angleEvent_.device.deviceName = deviceName;
            angleEvent_.device.typeId = deviceType;
            break;
        }
        case CMD_INNEROUTER: {
            innerOuterEvent_.device.deviceId = deviceId;
            innerOuterEvent_.device.deviceName = deviceName;
            innerOuterEvent_.device.typeId = deviceType;
            break;
        }
        case CMD_EXIST: {
            existEvent_.device.deviceId = deviceId;
            existEvent_.device.deviceName = deviceName;
            existEvent_.device.typeId = deviceType;
            break;
        }
        default:
            break;
    }
}


int InsertOpenCallback::OnCreate(RdbStore &store)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "OnCreate enter spatial");
    return SPATIALMANAGER_OK;
}

int InsertOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
{
    return SPATIALMANAGER_OK;
}

bool SpatialRdbManager::InitTimer()
{
    return timer_.Setup() == Utils::TIMER_ERR_OK;
}

bool SpatialRdbManager::StartTimer(int milliseconds, bool once)
{
    SPATIAL_LOGI(MODULE_ALGORITHM, "StartTimer: enter");
    uint32_t timerId = timer_.Register(std::bind(&SpatialRdbManager::UpdateDirectionData, this), milliseconds, once);
    return timerId != Utils::TIMER_ERR_DEAL_FAILED;
}

void SpatialRdbManager::StopTimer()
{
    timer_.Shutdown();
}
} // namespace Msdp
} // namespace OHOS